<template>
  <div>
    <el-row>
      <el-col :span="8">
        <el-input
          placeholder="在此输入json字符串或XML字符串..."
          type="textarea"
          :rows="23"
          resize="none"
          v-model="input"
          clearable>
        </el-input>
        <el-row style="float: left; margin-top: 10px">
          <el-button type="primary" @click="formatStr">格式化</el-button>
          <el-button type="info" @click="reset">清空结果</el-button>
        </el-row>
      </el-col>
      <el-col :span="16">
        <pre v-html="result">
        </pre>
      </el-col>
    </el-row>
  </div>
</template>

<script>
export default {
  name: 'Json',
  data () {
    return {
      input: '{"website":"lilaiqun.com","age":25,"address":{"province":"上海","district":"浦东新区"},"hobby":["足球","棒球","乒乓球"]}',
      result: '{\n&nbsp&nbsp<span class="key">"website"</span>: <span class="string">"lilaiqun.com"</span>,\n&nbsp&nbsp<span class="key">"age"</span>: <span class="number">25</span>,\n&nbsp&nbsp<span class="key">"name"</span>: <span class="string">"编程小工具"</span>\n}'
    }
  },
  methods: {
    formatStr () {
      let formatStr = this.formatJson(this.input)
      if (formatStr === false) {
        return
      }
      this.result = formatStr
      this.syntaxHighlight()
    },
    syntaxHighlight () {
      let result = this.result
      result = result.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
      // eslint-disable-next-line
      this.result = result.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
        let cls = 'number'
        if (/^"/.test(match)) {
          if (/:$/.test(match)) {
            cls = 'key'
          } else {
            cls = 'string'
          }
        } else if (/true|false/.test(match)) {
          cls = 'boolean'
        } else if (/null/.test(match)) {
          cls = 'null'
        }
        return '<span class="' + cls + '">' + match + '</span>'
      })
    },
    reset () {
      this.input = '{"website":"lilaiqun.com","age":15,"address":{"province":"浙江","city":"杭州","district":"西湖区"},"hobby":["足球","棒球","乒乓球"]}'
      this.result = ''
    },
    // 弹框提示
    openAlert (msg) {
      this.$alert(msg, '错误提示', {
        confirmButtonText: '确定',
        callback: action => {}
      })
    },
    // 格式化代码函数,已经用原生方式写好了不需要改动,直接引用就好
    formatJson (json, options) {
      let reg = null
      let formatted = ''
      let pad = 0
      let PADDING = '    '
      options = options || {}
      options.newlineAfterColonIfBeforeBraceOrBracket = (options.newlineAfterColonIfBeforeBraceOrBracket === true)
      options.spaceAfterColon = (options.spaceAfterColon !== false)
      if (typeof json !== 'string') {
        json = JSON.stringify(json)
      } else {
        try {
          json = JSON.parse(json)
        } catch (e) {
          this.openAlert('json格式错误')
          return false
        }
        json = JSON.stringify(json)
      }
      // eslint-disable-next-line
      reg = /([\{\}])/g
      json = json.replace(reg, '\r\n$1\r\n')
      // eslint-disable-next-line
      reg = /([\[\]])/g
      json = json.replace(reg, '\r\n$1\r\n')
      // eslint-disable-next-line
      reg = /(\,)/g
      json = json.replace(reg, '$1\r\n')
      // eslint-disable-next-line
      reg = /(\r\n\r\n)/g
      json = json.replace(reg, '\r\n')
      // eslint-disable-next-line
      reg = /\r\n\,/g
      json = json.replace(reg, ',')
      if (!options.newlineAfterColonIfBeforeBraceOrBracket) {
        // eslint-disable-next-line
        reg = /\:\r\n\{/g
        json = json.replace(reg, ':{')
        // eslint-disable-next-line
        reg = /\:\r\n\[/g
        json = json.replace(reg, ':[')
      }
      if (options.spaceAfterColon) {
        // eslint-disable-next-line
        reg = /\:/g
        json = json.replace(reg, ':')
      }
      (json.split('\r\n')).forEach(function (node, index) {
        let i = 0
        let indent = 0
        let padding = ''
        if (node.match(/\{$/) || node.match(/\[$/)) {
          indent = 1
        } else if (node.match(/\}/) || node.match(/\]/)) {
          if (pad !== 0) {
            pad -= 1
          }
        } else {
          indent = 0
        }
        for (i = 0; i < pad; i++) {
          padding += PADDING
        }
        formatted += padding + node + '\r\n'
        pad += indent
      })
      formatted = formatted.replace(/^\s+|\s+$/g, '')
      return formatted
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
.el-input {
  padding: 10px;
  height: 100%
}
.el-col {
  height: 100%
}
pre {
  padding: 5px; margin: 5px;
}
.string {
  color: green;
}
.number {
  color: darkorange;
}
.boolean {
  color: blue;
}
.null {
  color: magenta;
}
.key {
  color: red;
}
#jsonResult {
  height: 100%;
  box-sizing: border-box;
  padding: 5px 15px;
}
</style>
